/*****************************************************************
/
/     filename:   diff.c
/
/  description:   Implements the UNIX diff utility
/
/       author:   Szechy, Jared
/     login id:   cps444-n1.10
/
/        class:   CPS 444
/   instructor:   Perugini
/   assignment:   Homework #1
/
/     assigned:   August 26, 2009
/          due:   September 9, 2009
/
/***************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>

#ifndef MAX_CANON
#define MAX_CANON 8192
#endif

char *trimleadingspace(char *str);
char *trimtrailspace(char *str);
char *stripspace(char *str);

int main(int argc, char *argv[])
{
   int lflag = 0;
   int tflag = 0;
   int mflag = 0;
   int aflag = 0;
   int stdin1 = 0;
   int stdin2 = 0;
   int c, line;
   int fileErr = 0;
   char fileName1[25];
   char fileName2[25];
   FILE* file1 = NULL;
   FILE* file2 = NULL;
   char* read1 = (char *) malloc((MAX_CANON + 1)*sizeof(char));
   char* read2 = (char *) malloc((MAX_CANON + 1)*sizeof(char));

   opterr = 0;

   while ((c = getopt(argc, argv, "ltma")) != -1)
      switch (c)
      {
         case 'l':
            lflag = 1;
            break;
         case 't':
            tflag = 1;
            break;
         case 'm':
            mflag = 1;
            break;
         case 'a':
            aflag = 1;
            break;
         case '?':
            if (isprint(optopt))
               fprintf(stderr, "diff: invalid option -- '%c'\n", optopt);
            else
               fprintf(stderr, "Unknown option character `\\x%x;.\n", optopt);
            return 1;
         default:
            abort();
      }

   if(aflag)
   {
      if(lflag || tflag || mflag)
      {
         fprintf(stderr, "Option -a cannot be combined with any other options.\n");
         return 9;
      }
      lflag = tflag = mflag = 1;
   }

   // Store file names from arguments
   strcpy(fileName1, argv[argc - 2]);
   strcpy(fileName2, argv[argc - 1]);

   if(strcmp(fileName1,"-") == 0)
      stdin1 = 1;
   if(strcmp(fileName2,"-") == 0)
      stdin2 = 1;

   if(stdin1 == 0)
   {
      file1 = fopen(fileName1,"r");
      // Check that file1 opened
      if(file1 == NULL)
      {
         fprintf(stderr,"diff: %s: No such file or directory\n", fileName1);
         fileErr = 1;
      }
   }
   if(stdin2 == 0)
   {
      file2 = fopen(fileName2,"r");
      // Check that file2 opened
      if(file2 == NULL)
      {
         fprintf(stderr,"diff: %s: No such file or directory\n", fileName2);
         fileErr = 1;
      }
   }
   
	
   // Exit program with error code 1
   if(fileErr)
      return 1;

   line = 1;
   while(fgets(read1,MAX_CANON,file1))
   {
      if(stdin2)
         scanf(read2);
      else		 
         fgets(read2,MAX_CANON,file2);

      // Strip leading spaces
      if(lflag)
      {
         read1 = trimleadingspace(read1);
         read2 = trimleadingspace(read2);   
      }
      // Strip trailing spaces
      if(tflag)
      {
         read1 = trimtrailspace(read1);
         read2 = trimtrailspace(read2);
      }
      // Strip intermediate spaces
      if(mflag)
      {
         read1 = stripspace(read1);
         read2 = stripspace(read2);
      }

      // Compare lines
      if(strcmp(read1,read2))
      {
         printf("%i\n",line);
      }
      line++;
   }

   return 0;
}

char *trimleadingspace(char *str)
{
   while(isspace(*str))
      str++;

   return str;
}

char *trimtrailspace(char *str)
{
   char *end;

   end = str + strlen(str) - 1;
   while(end > str && isspace(*end))
      end--;

   *(end+1) = 0;

   return str;
}

char *stripspace(char *str)
{
   char *stripped = (char *) malloc(sizeof str);
   int length = 0;

   while(isspace(*str))
      str++;

   for(; *str; str++)
   {
      if(!isspace(*str))
      {
         length++;
         strncat(stripped,str,1);
      }
   } 
   *(stripped+length+1) = 0;
   stripped =  (char *) realloc(stripped, length * sizeof(char));

   return stripped;
}
